
#include "IGlobal.h"
#include <BReadWrite>
#include "member_BStyle.h"
#include "member_BObject.h"
#include "member_BStyle.h"

using namespace BWE;

#define member					(*(member_BStyle*)_ptr)
#define member_allocate()		_ptr = new member_BStyle(this)
#define member_release()		delete (member_BStyle*)_ptr

BStyle::BStyle(BStyle* parent)
{
	member_allocate();
	if (parent && parent != this)
		parent->addChild(this);
}
BStyle::BStyle(const BColor& color, BStyle* parent)
{
	member_allocate();
	if (parent && parent != this)
		parent->addChild(this);
	member.init(color);
}
BStyle::BStyle(const BString& name, BStyle* parent) : BObject(name)
{
	member_allocate();
	if (parent && parent != this)
		parent->addChild(this);
}
BStyle::BStyle(const BString& type, const BString& name, BStyle* parent) : BObject(name)
{
	member_allocate();
	if (parent && parent != this)
		parent->addChild(this);
	this->setType(type);
}
BStyle::BStyle(const BStyle& other) : BObject(other)
{
	member_allocate();
	this->copy(&other);
}
BStyle::~BStyle()
{
	member_release();
}

void BStyle::copy(const BStyle* other)
{
	member.valueMap = style_member(other)->valueMap;
	member.colorMap = style_member(other)->colorMap;
	member.imageMap = style_member(other)->imageMap;
	member.iconMap = style_member(other)->iconMap;
	member.namedValueMap = style_member(other)->namedValueMap;
	member.namedColorMap = style_member(other)->namedColorMap;
	member.namedImageMap = style_member(other)->namedImageMap;
	member.namedIconMap = style_member(other)->namedIconMap;
	member.textMap = style_member(other)->textMap;
	member.wordMap = style_member(other)->wordMap;
	member.transMap = style_member(other)->transMap;
	member.annexes = style_member(other)->annexes;
}
BStyle* BStyle::clone() const
{
	BStyle* style = new BStyle(member.type, this->name());
	style->copy(this);
	return style;
}

void BStyle::reset()
{
	member.heritable = true;
	member.descendant = true;
	member.valueMap.clear();
	member.namedValueMap.clear();
	member.colorMap.clear();
	member.namedColorMap.clear();
	member.imageMap.clear();
	member.namedImageMap.clear();
	member.iconMap.clear();
	member.namedIconMap.clear();
	member.transMap.clear();
	member.wordMap.clear();
	member.textMap.clear();
	member.annexes.clear();
	member.children.clear();
	member.raiseSignal(Signal_Dirty);
}
void BStyle::reset(const BColor& color)
{
	member.heritable = true;
	member.descendant = true;
	member.valueMap.clear();
	member.namedValueMap.clear();
	member.colorMap.clear();
	member.namedColorMap.clear();
	member.imageMap.clear();
	member.namedImageMap.clear();
	member.iconMap.clear();
	member.namedIconMap.clear();
	member.transMap.clear();
	member.wordMap.clear();
	member.textMap.clear();
	member.annexes.clear();
	member.children.clear();
	member.init(color);
	member.raiseSignal(Signal_Dirty);
}

void BStyle::setType(const BString& type)
{
	if (member.type != type)
	{
		member.type = type;
		member.raiseSignal(Signal_Dirty);
	}
}
const BString& BStyle::type() const
{
	return member.type;
}

void BStyle::setHeritable(bool heritable)
{
	if (member.heritable != heritable)
	{
		member.heritable = heritable;
		member.raiseSignal(Signal_Dirty);
	}
}
bool BStyle::heritable() const
{
	return member.heritable;
}

void BStyle::setDescendant(bool descendant)
{
	if (member.descendant != descendant)
	{
		member.descendant = descendant;
		member.raiseSignal(Signal_Dirty);
	}
}
bool BStyle::descendant() const
{
	return member.descendant;
}

void BStyle::setUnset(const BString& unset)
{
	if (member.unset != unset)
	{
		member.unset = unset;
		member.raiseSignal(Signal_Dirty);
	}
}
const BString& BStyle::unset() const
{
	return member.unset;
}

void BStyle::setFont(BFont* font)
{
	if (member.valueMap[Value_Font] != font)
	{
		member.valueMap[Value_Font] = font;
		member.raiseSignal(Signal_Dirty);
	}
}
const BFont* BStyle::font() const
{
	if (BFont* font = member.valueMap(Value_Font))
		return font;
	if (app_style != this)
		return app_style->font();
	return app_font;
}
BFont* BStyle::font()
{
	if (BFont* font = member.valueMap(Value_Font))
		return font;
	if (app_style != this)
		return app_style->font();
	return app_font;
}

void BStyle::setValue(StyleValue name, const BValue& value)
{
	if (name > Value_None && name < Value_Max)
	{
		member.valueMap[name] = value;
		member.raiseSignal(Signal_Dirty);
	}
}
bool BStyle::removeVlaue(StyleValue name)
{
	if (member.valueMap.remove(name))
	{
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	return false;
}
const BValue& BStyle::value(StyleValue name) const
{
	if (name > Value_None && name < Value_Max)
	{
		auto it = member.valueMap.find(name);
		if (it.valid())
			return *it;
		if (app_style != this)
			return app_style->value(name);
	}
	return member.valueMap.def();
}

bool BStyle::setValue(const BString& valueName, const BValue& value)
{
	if (valueName.empty())
		return false;
	member.namedValueMap[valueName] = value;
	member.raiseSignal(Signal_Dirty);
	return true;
}
bool BStyle::removeValue (const BString& valueName)
{
	if (member.namedValueMap.remove(valueName))
	{
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	return false;
}
const BValue& BStyle::value(const BString& valueName) const
{
	if (valueName.size())
	{
		auto it = member.namedValueMap.find(valueName);
		if (it.valid())
			return *it;
		if (app_style != this)
			return app_style->value(valueName);
	}
	return member.namedValueMap.def();
}
const BValue& BStyle::value(const char* valueName) const
{
	if (valueName)
	{
		auto it = member.namedValueMap.find(valueName);
		if (it.valid())
			return *it;
		if (app_style != this)
			return app_style->value(valueName);
	}
	return member.namedValueMap.def();
}

bool BStyle::hasValue(StyleValue name) const
{
	auto it = member.valueMap.find(name);
	return it.valid();
}
bool BStyle::valueNames(BArray<StyleValue>& names) const
{
	names.reset();
	for (auto it = member.valueMap.begin(); it.valid(); ++it)
	{
		names.append(it.key());
	}
	return names.size() > 0;
}
bool BStyle::valueNames(BStringArray& names) const
{
	names.reset();
	for (auto it = member.namedValueMap.begin(); it.valid(); ++it)
	{
		names.append(it.key());
	}
	return names.size() > 0;
}

bool BStyle::setColor(StyleColor name, State state, const BColor& color)
{
	if (state == State_None)
	{
		member.colorMap[name] = color;
		member.colorMap[name + State_Normal] = color;
		member.colorMap[name + State_Normal_Hovered] = color;
		member.colorMap[name + State_Normal_Pressed] = color;
		member.colorMap[name + State_Normal_Selected] = color;

		member.colorMap[name + State_Actived] = color;
		member.colorMap[name + State_Actived_Hovered] = color;
		member.colorMap[name + State_Actived_Pressed] = color;
		member.colorMap[name + State_Actived_Selected] = color;

		member.colorMap[name + State_Checked] = color;
		member.colorMap[name + State_Checked_Hovered] = color;
		member.colorMap[name + State_Checked_Pressed] = color;
		member.colorMap[name + State_Checked_Selected] = color;

		member.colorMap[name + State_Disable] = color;
		member.colorMap[name + State_Disable_Hovered] = color;
		member.colorMap[name + State_Disable_Pressed] = color;
		member.colorMap[name + State_Disable_Selected] = color;

		member.colorMap[name + State_Hovered] = color;
		member.colorMap[name + State_Pressed] = color;
		member.colorMap[name + State_Selected] = color;

		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Normal)
	{
		member.colorMap[name] = color;
		member.colorMap[name + State_Normal] = color;
		member.colorMap[name + State_Normal_Hovered] = color;
		member.colorMap[name + State_Normal_Pressed] = color;
		member.colorMap[name + State_Normal_Selected] = color;
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Actived)
	{
		member.colorMap[name + State_Actived] = color;
		member.colorMap[name + State_Actived_Hovered] = color;
		member.colorMap[name + State_Actived_Pressed] = color;
		member.colorMap[name + State_Actived_Selected] = color;
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Checked)
	{
		member.colorMap[name + State_Checked] = color;
		member.colorMap[name + State_Checked_Hovered] = color;
		member.colorMap[name + State_Checked_Pressed] = color;
		member.colorMap[name + State_Checked_Selected] = color;
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Disable)
	{
		member.colorMap[name + State_Disable] = color;
		member.colorMap[name + State_Disable_Hovered] = color;
		member.colorMap[name + State_Disable_Pressed] = color;
		member.colorMap[name + State_Disable_Selected] = color;
		member.raiseSignal(Signal_Dirty);
		return true;
	}

	if (state == State_Hovered)
	{
		member.colorMap[name + State_Hovered] = color;
		member.colorMap[name + State_Normal_Hovered] = color;
		member.colorMap[name + State_Actived_Hovered] = color;
		member.colorMap[name + State_Checked_Hovered] = color;
		member.colorMap[name + State_Disable_Hovered] = color;
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Pressed)
	{
		member.colorMap[name + State_Pressed] = color;
		member.colorMap[name + State_Normal_Pressed] = color;
		member.colorMap[name + State_Actived_Pressed] = color;
		member.colorMap[name + State_Checked_Pressed] = color;
		member.colorMap[name + State_Disable_Pressed] = color;
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Selected)
	{
		member.colorMap[name + State_Selected] = color;
		member.colorMap[name + State_Normal_Selected] = color;
		member.colorMap[name + State_Actived_Selected] = color;
		member.colorMap[name + State_Checked_Selected] = color;
		member.colorMap[name + State_Disable_Selected] = color;
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	member.colorMap[name + state] = color;
	member.raiseSignal(Signal_Dirty);
	return true;
}
bool BStyle::removeColor(StyleColor name, State state)
{
	if (state == State_None)
	{
		member.colorMap.remove(name + State_None);
		member.colorMap.remove(name + State_Normal);
		member.colorMap.remove(name + State_Normal_Hovered);
		member.colorMap.remove(name + State_Normal_Pressed);
		member.colorMap.remove(name + State_Normal_Selected);

		member.colorMap.remove(name + State_Actived);
		member.colorMap.remove(name + State_Actived_Hovered);
		member.colorMap.remove(name + State_Actived_Pressed);
		member.colorMap.remove(name + State_Actived_Selected);

		member.colorMap.remove(name + State_Checked);
		member.colorMap.remove(name + State_Checked_Hovered);
		member.colorMap.remove(name + State_Checked_Pressed);
		member.colorMap.remove(name + State_Checked_Selected);

		member.colorMap.remove(name + State_Disable);
		member.colorMap.remove(name + State_Disable_Hovered);
		member.colorMap.remove(name + State_Disable_Pressed);
		member.colorMap.remove(name + State_Disable_Selected);

		member.colorMap.remove(name + State_Hovered);
		member.colorMap.remove(name + State_Pressed);
		member.colorMap.remove(name + State_Selected);

		return true;
	}
	if (state == State_Normal)
	{
		member.colorMap.remove(name + State_None);
		member.colorMap.remove(name + State_Normal);
		member.colorMap.remove(name + State_Normal_Hovered);
		member.colorMap.remove(name + State_Normal_Pressed);
		member.colorMap.remove(name + State_Normal_Selected);
		return true;
	}
	if (state == State_Actived)
	{
		member.colorMap.remove(name + State_Actived);
		member.colorMap.remove(name + State_Actived_Hovered);
		member.colorMap.remove(name + State_Actived_Pressed);
		member.colorMap.remove(name + State_Actived_Selected);
		return true;
	}
	if (state == State_Checked)
	{
		member.colorMap.remove(name + State_Checked);
		member.colorMap.remove(name + State_Checked_Hovered);
		member.colorMap.remove(name + State_Checked_Pressed);
		member.colorMap.remove(name + State_Checked_Selected);
		return true;
	}
	if (state == State_Disable)
	{
		member.colorMap.remove(name + State_Disable);
		member.colorMap.remove(name + State_Disable_Hovered);
		member.colorMap.remove(name + State_Disable_Pressed);
		member.colorMap.remove(name + State_Disable_Selected);
		return true;
	}

	if (state == State_Hovered)
	{
		member.colorMap.remove(name + State_Hovered);
		member.colorMap.remove(name + State_Normal_Hovered);
		member.colorMap.remove(name + State_Actived_Hovered);
		member.colorMap.remove(name + State_Checked_Hovered);
		member.colorMap.remove(name + State_Disable_Hovered);
		return true;
	}
	if (state == State_Pressed)
	{
		member.colorMap.remove(name + State_Pressed);
		member.colorMap.remove(name + State_Normal_Pressed);
		member.colorMap.remove(name + State_Actived_Pressed);
		member.colorMap.remove(name + State_Checked_Pressed);
		member.colorMap.remove(name + State_Disable_Pressed);
		return true;
	}
	if (state == State_Selected)
	{
		member.colorMap.remove(name + State_Selected);
		member.colorMap.remove(name + State_Normal_Selected);
		member.colorMap.remove(name + State_Actived_Selected);
		member.colorMap.remove(name + State_Checked_Selected);
		member.colorMap.remove(name + State_Disable_Selected);
		return true;
	}
	return member.colorMap.remove(name + state);
}
const BColor& BStyle::color(StyleColor name, State state) const
{
	if (name > 0)
	{
		auto it = member.colorMap.find(name + state);
		if (it.valid())
			return *it;
		if (app_style != this)
			return app_style->color(name, state);
	}
	return member.colorMap.def();
}

bool BStyle::setColor(const BString& colorName, const BColor& color)
{
	if (colorName.empty())
		return false;
	member.namedColorMap[colorName] = color;
	member.raiseSignal(Signal_Dirty);
	return true;
}
bool BStyle::removeColor(const BString& colorName)
{
	if (member.namedColorMap.remove(colorName))
	{
		member.raiseSignal(Signal_Dirty);
		return false;
	}
	return true;
}
const BColor& BStyle::color(const BString& colorName) const
{
	if (colorName.size())
	{
		auto it = member.namedColorMap.find(colorName);
		if (it.valid())
			return *it;
		if (app_style != this)
			return app_style->color(colorName);
	}
	return member.namedColorMap.def();
}
const BColor& BStyle::color(const char* colorName) const
{
	if (colorName)
	{
		auto it = member.namedColorMap.find(colorName);
		if (it.valid())
			return *it;
		if (app_style != this)
			return app_style->color(colorName);
	}
	return member.namedColorMap.def();
}

bool BStyle::hasColor(StyleColor name) const
{
	auto it = member.colorMap.find(name);
	return it.valid();
}
bool BStyle::hasColor(const char* name) const
{
	auto it = member.namedColorMap.find(name);
	return it.valid();
}
bool BStyle::hasColor(const BString& name) const
{
	auto it = member.namedColorMap.find(name);
	return it.valid();
}
bool BStyle::colorNames(BStringArray& names) const
{
	names.reset();
	for (auto it = member.namedColorMap.begin(); it.valid(); ++it)
	{
		names.append(it.key());
	}
	return names.size() > 0;
}

bool BStyle::setImage(StyleImage name, State state, BImage* image)
{
	if (state == State_None)
	{
		member.imageMap[name] = image;
		member.imageMap[name + State_Normal] = image;
		member.imageMap[name + State_Normal_Hovered] = image;
		member.imageMap[name + State_Normal_Pressed] = image;
		member.imageMap[name + State_Normal_Selected] = image;

		member.imageMap[name + State_Actived] = image;
		member.imageMap[name + State_Actived_Hovered] = image;
		member.imageMap[name + State_Actived_Pressed] = image;
		member.imageMap[name + State_Actived_Selected] = image;

		member.imageMap[name + State_Checked] = image;
		member.imageMap[name + State_Checked_Hovered] = image;
		member.imageMap[name + State_Checked_Pressed] = image;
		member.imageMap[name + State_Checked_Selected] = image;

		member.imageMap[name + State_Disable] = image;
		member.imageMap[name + State_Disable_Hovered] = image;
		member.imageMap[name + State_Disable_Pressed] = image;
		member.imageMap[name + State_Disable_Selected] = image;

		member.imageMap[name + State_Hovered] = image;
		member.imageMap[name + State_Pressed] = image;
		member.imageMap[name + State_Selected] = image;

		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Normal)
	{
		member.imageMap[name] = image;
		member.imageMap[name + State_Normal] = image;
		member.imageMap[name + State_Normal_Hovered] = image;
		member.imageMap[name + State_Normal_Pressed] = image;
		member.imageMap[name + State_Normal_Selected] = image;
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Actived)
	{
		member.imageMap[name + State_Actived] = image;
		member.imageMap[name + State_Actived_Hovered] = image;
		member.imageMap[name + State_Actived_Pressed] = image;
		member.imageMap[name + State_Actived_Selected] = image;
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Checked)
	{
		member.imageMap[name + State_Checked] = image;
		member.imageMap[name + State_Checked_Hovered] = image;
		member.imageMap[name + State_Checked_Pressed] = image;
		member.imageMap[name + State_Checked_Selected] = image;
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Disable)
	{
		member.imageMap[name + State_Disable] = image;
		member.imageMap[name + State_Disable_Hovered] = image;
		member.imageMap[name + State_Disable_Pressed] = image;
		member.imageMap[name + State_Disable_Selected] = image;
		member.raiseSignal(Signal_Dirty);
		return true;
	}

	if (state == State_Hovered)
	{
		member.imageMap[name + State_Hovered] = image;
		member.imageMap[name + State_Normal_Hovered] = image;
		member.imageMap[name + State_Actived_Hovered] = image;
		member.imageMap[name + State_Checked_Hovered] = image;
		member.imageMap[name + State_Disable_Hovered] = image;
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Pressed)
	{
		member.imageMap[name + State_Pressed] = image;
		member.imageMap[name + State_Normal_Pressed] = image;
		member.imageMap[name + State_Actived_Pressed] = image;
		member.imageMap[name + State_Checked_Pressed] = image;
		member.imageMap[name + State_Disable_Pressed] = image;
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Selected)
	{
		member.imageMap[name + State_Selected] = image;
		member.imageMap[name + State_Normal_Selected] = image;
		member.imageMap[name + State_Actived_Selected] = image;
		member.imageMap[name + State_Checked_Selected] = image;
		member.imageMap[name + State_Disable_Selected] = image;
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	member.imageMap[name + state] = image;
	member.raiseSignal(Signal_Dirty);
	return true;
}
bool BStyle::removeImage(StyleImage name, State state)
{
	if (state == State_None)
	{
		member.imageMap.remove(name + State_None);
		member.imageMap.remove(name + State_Normal);
		member.imageMap.remove(name + State_Normal_Hovered);
		member.imageMap.remove(name + State_Normal_Pressed);
		member.imageMap.remove(name + State_Normal_Selected);

		member.imageMap.remove(name + State_Actived);
		member.imageMap.remove(name + State_Actived_Hovered);
		member.imageMap.remove(name + State_Actived_Pressed);
		member.imageMap.remove(name + State_Actived_Selected);

		member.imageMap.remove(name + State_Checked);
		member.imageMap.remove(name + State_Checked_Hovered);
		member.imageMap.remove(name + State_Checked_Pressed);
		member.imageMap.remove(name + State_Checked_Selected);

		member.imageMap.remove(name + State_Disable);
		member.imageMap.remove(name + State_Disable_Hovered);
		member.imageMap.remove(name + State_Disable_Pressed);
		member.imageMap.remove(name + State_Disable_Selected);

		member.imageMap.remove(name + State_Hovered);
		member.imageMap.remove(name + State_Pressed);
		member.imageMap.remove(name + State_Selected);

		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Normal)
	{
		member.imageMap.remove(name + State_None);
		member.imageMap.remove(name + State_Normal);
		member.imageMap.remove(name + State_Normal_Hovered);
		member.imageMap.remove(name + State_Normal_Pressed);
		member.imageMap.remove(name + State_Normal_Selected);
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Actived)
	{
		member.imageMap.remove(name + State_Actived);
		member.imageMap.remove(name + State_Actived_Hovered);
		member.imageMap.remove(name + State_Actived_Pressed);
		member.imageMap.remove(name + State_Actived_Selected);
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Checked)
	{
		member.imageMap.remove(name + State_Checked);
		member.imageMap.remove(name + State_Checked_Hovered);
		member.imageMap.remove(name + State_Checked_Pressed);
		member.imageMap.remove(name + State_Checked_Selected);
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Disable)
	{
		member.imageMap.remove(name + State_Disable);
		member.imageMap.remove(name + State_Disable_Hovered);
		member.imageMap.remove(name + State_Disable_Pressed);
		member.imageMap.remove(name + State_Disable_Selected);
		member.raiseSignal(Signal_Dirty);
		return true;
	}

	if (state == State_Hovered)
	{
		member.imageMap.remove(name + State_Hovered);
		member.imageMap.remove(name + State_Normal_Hovered);
		member.imageMap.remove(name + State_Actived_Hovered);
		member.imageMap.remove(name + State_Checked_Hovered);
		member.imageMap.remove(name + State_Disable_Hovered);
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Pressed)
	{
		member.imageMap.remove(name + State_Pressed);
		member.imageMap.remove(name + State_Normal_Pressed);
		member.imageMap.remove(name + State_Actived_Pressed);
		member.imageMap.remove(name + State_Checked_Pressed);
		member.imageMap.remove(name + State_Disable_Pressed);
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (state == State_Selected)
	{
		member.imageMap.remove(name + State_Selected);
		member.imageMap.remove(name + State_Normal_Selected);
		member.imageMap.remove(name + State_Actived_Selected);
		member.imageMap.remove(name + State_Checked_Selected);
		member.imageMap.remove(name + State_Disable_Selected);
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	if (member.imageMap.remove(name + state))
	{
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	return false;
}
BImage* BStyle::image(StyleImage name, State state) const
{
	if (name > 0)
	{
		auto it = member.imageMap.find(name + state);
		if (it.valid())
			return *it;
		if (app_style != this && app_style)
			return app_style->image(name, state);
	}
	return member.imageMap.def();
}

bool BStyle::setImage(const BString& name, BImage* image)
{
	if (name.empty())
		return false;
	member.namedImageMap[name] = image;
	member.raiseSignal(Signal_Dirty);
	return true;
}
bool BStyle::removeImage(const BString& name)
{
	if (member.namedImageMap.remove(name))
	{
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	return false;
}
BImage* BStyle::image(const BString& name) const
{
	if (name.size())
	{
		auto it = member.namedImageMap.find(name);
		if (it.valid())
			return *it;
		if (app_style != this)
			return app_style->image(name);
	}
	return member.namedImageMap.def();
}
BImage* BStyle::image(const char* name) const
{
	if (name)
	{
		auto it = member.namedImageMap.find(name);
		if (it.valid())
			return *it;
		if (app_style != this)
			return app_style->image(name);
	}
	return member.namedImageMap.def();
}

bool BStyle::hasImage(StyleImage name, State state) const
{
	auto it = member.imageMap.find(name + state);
	return it.valid();
}
bool BStyle::hasImage(const char* name) const
{
	auto it = member.namedImageMap.find(name);
	return it.valid();
}
bool BStyle::hasImage(const BString& name) const
{
	auto it = member.namedImageMap.find(name);
	return it.valid();
}
bool BStyle::imageNames(BStringArray& names) const
{
	names.reset();
	for (auto it = member.namedImageMap.begin(); it.valid(); ++it)
	{
		names.append(it.key());
	}
	return names.size() > 0;
}

bool BStyle::setIcon(StyleIcon name, BIcon* icon)
{
	if (name < 1)
		return false;
	member.iconMap[name] = icon;
	member.raiseSignal(Signal_Dirty);
	return true;

}
bool BStyle::removeIcon(StyleIcon name)
{
	if (member.iconMap.remove(name))
	{
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	return false;
}
BIcon* BStyle::icon(StyleIcon name) const
{
	if (name > 0)
	{
		auto it = member.iconMap.find(name);
		if (it.valid())
			return *it;
		if (app_style != this)
			return app_style->icon(name);
	}
	return member.iconMap.def();
}

bool BStyle::setIcon(const BString& name, BIcon* icon)
{
	if (icon)
	{
		member.namedIconMap[name] = icon;
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	return false;
}
bool BStyle::removeIcon(const BString& name)
{
	if (member.namedIconMap.remove(name))
	{
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	return false;
}
BIcon* BStyle::icon(const BString& name) const
{
	if (name.size())
	{
		auto it = member.namedIconMap.find(name);
		if (it.valid())
			return *it;
		if (app_style != this)
			return app_style->icon(name);
	}
	return member.namedIconMap.def();
}
BIcon* BStyle::icon(const char* name) const
{
	if (name)
	{
		auto it = member.namedIconMap.find(name);
		if (it.valid())
			return *it;
		if (app_style != this)
			return app_style->icon(name);
	}
	return member.namedIconMap.def();
}

bool BStyle::hasIcon(StyleIcon name) const
{
	auto it = member.iconMap.find(name);
	return it.valid();
}
bool BStyle::hasIcon(const char* name) const
{
	auto it = member.namedIconMap.find(name);
	return it.valid();
}
bool BStyle::hasIcon(const BString& name) const
{
	auto it = member.namedIconMap.find(name);
	return it.valid();
}
bool BStyle::iconNames(BStringArray& names) const
{
	names.reset();
	for (auto it = member.namedIconMap.begin(); it.valid(); ++it)
	{
		names.append(it.key());
	}
	return names.size() > 0;
}

bool BStyle::setText(const BString& name, const BString& text)
{
	if (name.empty())
		return false;
	member.textMap[name] = text;
	member.raiseSignal(Signal_Dirty);
	return true;
}
bool BStyle::removeText(const BString& name)
{
	if (member.textMap.remove(name))
	{
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	return false;
}
const BString& BStyle::text(const BString& name) const
{
	auto it = member.textMap.find(name);
	if (it.valid())
		return *it;
	if (app_style != this)
		return app_style->text(name);
	return member.textMap.def();
}
const BString& BStyle::text(const char* name) const
{
	auto it = member.textMap.find(name);
	if (it.valid())
		return *it;
	if (app_style != this)
		return app_style->text(name);
	return member.textMap.def();
}

bool BStyle::hasText(const char* name) const
{
	auto it = member.textMap.find(name);
	return it.valid();
}
bool BStyle::hasText(const BString& name) const
{
	auto it = member.textMap.find(name);
	return it.valid();
}
bool BStyle::textNames(BStringArray& names) const
{
	names.reset();
	for (auto it = member.textMap.begin(); it.valid(); ++it)
	{
		names.append(it.key());
	}
	return names.size() > 0;
}

bool BStyle::setWord(const BString& name, const BString& word)
{
	if (name.empty())
		return false;
	member.wordMap[name] = word;
	member.raiseSignal(Signal_Dirty);
	return true;
}
bool BStyle::removeWord(const BString& name)
{
	if (member.wordMap.remove(name))
	{
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	return false;
}
const BString& BStyle::word(const BString& name) const
{
	auto it = member.wordMap.find(name);
	if (it.valid())
		return *it;
	if (app_style != this)
		return app_style->word(name);
	return member.wordMap.def();
}
const BString& BStyle::word(const char* name) const
{
	auto it = member.wordMap.find(name);
	if (it.valid())
		return *it;
	if (app_style != this)
		return app_style->word(name);
	return member.wordMap.def();
}

bool BStyle::hasWord(const char* name) const
{
	auto it = member.wordMap.find(name);
	return it.valid();
}
bool BStyle::hasWord(const BString& name) const
{
	auto it = member.wordMap.find(name);
	return it.valid();
}
bool BStyle::wordNames(BStringArray& names) const
{
	names.reset();
	for (auto it = member.wordMap.begin(); it.valid(); ++it)
	{
		names.append(it.key());
	}
	return names.size() > 0;
}

bool BStyle::setTrans(const BString& text, const BString& trans)
{
	if (text.empty())
		return false;
	member.transMap[text] = trans;
	member.raiseSignal(Signal_Dirty);
	return true;
}
bool BStyle::removeTrans(const BString& text)
{
	if (member.transMap.remove(text))
	{
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	return false;
}
const BString& BStyle::trans(const BString& text) const
{
	auto it = member.transMap.find(text);
	if (it.valid())
		return *it;
	if (app_style != this)
		return app_style->trans(text);
	return member.transMap.def();
}
const BString& BStyle::trans(const char* text) const
{
	auto it = member.transMap.find(text);
	if (it.valid())
		return *it;
	if (app_style != this)
		return app_style->trans(text);
	return member.transMap.def();
}

bool BStyle::hasTrans(const char* text) const
{
	auto it = member.transMap.find(text);
	return it.valid();
}
bool BStyle::hasTrans(const BString& text) const
{
	auto it = member.transMap.find(text);
	return it.valid();
}
bool BStyle::transNames(BStringArray& texts) const
{
	texts.reset();
	for (auto it = member.transMap.begin(); it.valid(); ++it)
	{
		texts.append(it.key());
	}
	return texts.size() > 0;
}

bool BStyle::translate(const BString& text, BString& output) const
{
	if (text.empty())
	{
		output.reset();
		return false;
	}
	output = text;
	output.lower();
	output = this->trans(output);
	if (output.size())
		return true;
	BString word;
	int pos = 0;
	while (pos < text.size())
	{
		while (pos < text.size())
		{
			char code = text[pos];
			if (code > 0 && isalpha(text[pos]))
				break;
			output.append(text[pos]);
			pos++;
		}
		int end = pos;
		while (end < text.size())
		{
			char code = text[end];
			if (code > 0 && !isalpha(text[end]))
				break;
			end++;
		}
		if (end > pos)
		{
			word.reset(text, pos, end);
			word.lower();
			const BString& tw = this->word(word);
			if (tw.size())
			{
				output -= ' ';
				output << tw;
			}
			else
			{
				output.append(text, pos, end);
			}
			pos = end;
		}
	}
	if (output == text)
	{
		output.reset();
		return false;
	}
	return true;
}
const BString& BStyle::translate(const BString& text) const
{
	BString& output = member.textMap.def();
	translate(text, output);
	return output;
}

void BStyle::clearAll()
{
	bool dirty = false;
	if (member.valueMap.clear())
		dirty = true;
	if (member.namedValueMap.clear())
		dirty = true;
	if (member.colorMap.clear())
		dirty = true;
	if (member.namedColorMap.clear())
		dirty = true;
	if (member.imageMap.clear())
		dirty = true;
	if (member.namedImageMap.clear())
		dirty = true;
	if (member.iconMap.clear())
		dirty = true;
	if (member.namedIconMap.clear())
		dirty = true;
	if (member.transMap.clear())
		dirty = true;
	if (member.wordMap.clear())
		dirty = true;
	if (member.textMap.clear())
		dirty = true;
	if (dirty)
		member.raiseSignal(Signal_Dirty);
}
bool BStyle::clearValues()
{
	if (member.valueMap.empty())
		return false;
	member.valueMap.clear();
	member.namedValueMap.clear();
	member.raiseSignal(Signal_Dirty);
	return true;
}
bool BStyle::clearColors()
{
	if (member.colorMap.empty() && member.namedColorMap.empty())
		return false;
	member.colorMap.clear();
	member.namedColorMap.clear();
	member.raiseSignal(Signal_Dirty);
	return true;
}
bool BStyle::clearImages()
{
	if (member.imageMap.empty() && member.namedImageMap.empty())
		return false;
	member.imageMap.clear();
	member.namedImageMap.clear();
	member.raiseSignal(Signal_Dirty);
	return true;
}
bool BStyle::clearIcons()
{
	if (member.iconMap.empty() && member.namedIconMap.empty())
		return false;
	member.iconMap.clear();
	member.namedIconMap.clear();
	member.raiseSignal(Signal_Dirty);
	return true;
}
bool BStyle::clearTrans()
{
	if (member.transMap.empty())
		return false;
	member.transMap.clear();
	member.raiseSignal(Signal_Dirty);
	return true;
}
bool BStyle::clearWords()
{
	if (member.wordMap.empty())
		return false;
	member.wordMap.clear();
	member.raiseSignal(Signal_Dirty);
	return true;
}
bool BStyle::clearTexts()
{
	if (member.textMap.empty())
		return false;
	member.textMap.clear();
	member.raiseSignal(Signal_Dirty);
	return true;
}
bool BStyle::cleanTranslation()
{
	bool dirty = false;
	if (member.transMap.clear())
		dirty = true;
	if (member.wordMap.clear())
		dirty = true;
	if (member.textMap.clear())
		dirty = true;
	for (int i = 0; i < member.annexes.size(); i++)
	{
		BStyle* annex = member.annexes[i];
		if (annex->cleanTranslation())
			dirty = true;
	}
	for (int i = 0; i < member.children.size(); i++)
	{
		BStyle* child = member.children[i];
		if (child->cleanTranslation())
			dirty = true;
	}
	if (dirty)
	{
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	return false;
}

BStyle* BStyle::root()
{
	BStyle* style = this;
	while (style_member(style)->parent)
		style = style_member(style)->parent;
	return style;
}
const BStyle* BStyle::root() const
{
	const BStyle* style = this;
	while (style_member(style)->parent)
		style = style_member(style)->parent;
	return style;
}

BStyle* BStyle::parent()
{
	return member.parent;
}
const BStyle* BStyle::parent() const
{
	return member.parent;
}

BStyle* BStyle::parent(const BString& name)
{
	BStyle* parent = this->parent();
	while (parent && parent->name() != name)
		parent = parent->parent();
	return parent;
}
const BStyle* BStyle::parent(const BString& name) const
{
	const BStyle* parent = this->parent();
	while (parent && parent->name() != name)
		parent = parent->parent();
	return parent;
}

bool BStyle::addChild(BStyle* child)
{
	if (!child || child == this)
		return false;
	if (child == this)
		return false;
	if (member.children.contain(child))
		return true;
	member.children.append(child);
	if (style_member(child)->parent)
		style_member(child)->parent->removeChild(child);
	style_member(child)->parent = this;
	member.raiseSignal(Signal_Insert, BValue(child, this));
	member.raiseSignal(Signal_Dirty);
	return true;
}
BStyle* BStyle::addChild(const BString& name)
{
	BStyle* style = new BStyle(name);
	addChild(style);
	return style;
}
BStyle* BStyle::addChild(const BString& type, const BString& name)
{
	BStyle* style = new BStyle(type, name);
	addChild(style);
	return style;
}

bool BStyle::removeChild(BStyle* child)
{
	if (!child)
		return false;
	if (child == this)
		return false;
	if (!member.children.contain(child))
		return false;
	BHolder<BStyle> holder(child);
	style_member(child)->parent = 0;
	member.children.remove(child);
	member.raiseSignal(Signal_Remove, BValue(child, this));
	return true;
}
bool BStyle::removeChild(const BString& name)
{
	for (int i = 0; i < member.children.size(); i++)
	{
		BStyle* child = member.children[i];
		if (child->name() == name)
		{
			return removeChild(child);
		}
	}
	return false;
}
bool BStyle::removeChild(const BString& type, const BString& name)
{
	for (int i = 0; i < member.children.size(); i++)
	{
		BStyle* child = member.children[i];
		if (child->type() == type && child->name() == name)
		{
			return removeChild(child);
		}
	}
	return false;
}
void BStyle::clearChildren()
{
	while (BStyle* child = member.children.last())
	{
		this->removeChild(child);
	}
}

int BStyle::childCount() const
{
	return member.children.size();
}
BStyle* BStyle::child(int index)
{
	return member.children(index);
}
const BStyle* BStyle::child(int index) const
{
	return member.children(index);
}

BStyle* BStyle::child(const BString& type, const BString& name)
{
	for (int i = 0; i < member.children.size(); i++)
	{
		BStyle* child = member.children[i];
		if (child->name() != name)
			continue;
		if (child->type() != type)
			continue;
		return child;
	}
	return 0;
}
const BStyle* BStyle::child(const BString& type, const BString& name) const
{
	for (int i = 0; i < member.children.size(); i++)
	{
		BStyle* child = member.children[i];
		if (child->name() != name)
			continue;
		if (child->type() != type)
			continue;
		return child;
	}
	return 0;
}

BStyle* BStyle::locate(const BString& path)
{
	if (path.empty())
		return this;
	BStringArray textlst = path.split('/');
	BStyle* style = this->child(textlst.first());
	textlst.remove(0);
	while (style && textlst.size())
	{
		const BString& text = textlst.first();
		style = style->child(text);
		textlst.remove(0);
	}
	return style;
}
const BStyle* BStyle::locate(const BString& path) const
{
	if (path.empty())
		return this;
	BStringArray textlst = path.split('/');
	const BStyle* style = this->child(textlst.first());
	textlst.remove(0);
	while (style && textlst.size())
	{
		const BString& text = textlst.first();
		style = style->child(text);
		textlst.remove(0);
	}
	return style;
}

BStyle* BStyle::prev()
{
	if (BStyle* parent = member.parent)
	{
		BArray<BStyleHolder>& children = style_member(parent)->children;
		int pos = children.find(this);
		return children.at(pos - 1);
	}
	return 0;
}
const BStyle* BStyle::prev() const
{
	if (BStyle* parent = member.parent)
	{
		BArray<BStyleHolder>& children = style_member(parent)->children;
		int pos = children.find(this);
		return children.at(pos - 1);
	}
	return 0;
}
BStyle* BStyle::next()
{
	if (BStyle* parent = member.parent)
	{
		BArray<BStyleHolder>& children = style_member(parent)->children;
		int pos = children.find(this);
		return children.at(pos + 1);
	}
	return 0;
}
const BStyle* BStyle::next() const
{
	if (BStyle* parent = member.parent)
	{
		BArray<BStyleHolder>& children = style_member(parent)->children;
		int pos = children.find(this);
		return children.at(pos + 1);
	}
	return 0;
}

bool BStyle::contain(const BStyle* style) const
{
	if (!style || style == this)
		return false;
	for (int i = 0; i < member.children.size(); i++)
	{
		if (member.children[i] == style)
			return true;
	}
	return false;
}
bool BStyle::above(const BStyle* style) const
{
	if (!style || style == this)
		return false;
	BStyle* parent = style_member(style)->parent;
	while (parent)
	{
		if (parent == this)
			return true;
		parent = style_member(parent)->parent;
	}
	return false;
}
bool BStyle::under(const BStyle* style) const
{
	if (!style || style == this)
		return false;
	BStyle* parent = member.parent;
	while (parent)
	{
		if (parent == style)
			return true;
		parent = style_member(parent)->parent;
	}
	return false;
}

bool BStyle::setIndex(int index)
{
	if (member.parent)
	{
		BStyleHolderArray& children = style_member(member.parent)->children;
		int pos = children.find(this);
		if (children.move(pos, index))
		{
			member.raiseSignal(Signal_OrderChanged, index);
			return true;
		}
	}
	return false;
}
int BStyle::index() const
{
	if (BStyle* parent = member.parent)
	{
		BArray<BStyleHolder>& children = style_member(parent)->children;
		return children.find(this);
	}
	return -1;
}
int BStyle::level() const
{
	int level = 0;
	const BStyle* parent = member.parent;
	while (parent)
	{
		level++;
		parent = style_member(parent)->parent;
	}
	return level;
}

bool BStyle::raise()
{
	if (member.parent)
	{
		BStyleHolderArray& children = style_member(member.parent)->children;
		int pos = children.find(this);
		if (children.move(pos, 0))
		{
			member.raiseSignal(Signal_OrderChanged, 0);
			return true;
		}
	}
	return false;
}
bool BStyle::lower()
{
	if (member.parent)
	{
		BStyleHolderArray& children = style_member(member.parent)->children;
		int pos = children.find(this);
		int index = children.size() - 1;
		if (children.move(pos, index))
		{
			member.raiseSignal(Signal_OrderChanged, index);
			return true;
		}
	}
	return false;
}

BStyle* BStyle::addAnnex(const BString& name)
{
	BStyle* annex = new BStyle(name);
	member.annexes.append(annex);
	member.raiseSignal(Signal_Dirty);
	return annex;
}
bool BStyle::addAnnex(BStyle* annex)
{
	if (!annex || annex == this)
		return false;
	member.annexes.append(annex);
	member.raiseSignal(Signal_Dirty);
	return true;
}

bool BStyle::removeAnnex(const BString& name)
{
	for (int i = 0; i < member.annexes.size(); i++)
	{
		BStyle* annex = member.annexes[i];
		if (annex->name() == name)
		{
			if (member.annexes.remove(i))
			{
				member.raiseSignal(Signal_Dirty);
				return true;
			}
		}
	}
	return false;
}
bool BStyle::removeAnnex(BStyle* annex)
{
	if (member.annexes.remove(annex))
	{
		member.raiseSignal(Signal_Dirty);
		return true;
	}
	return false;
}
bool BStyle::clearAnnexes()
{
	member.annexes.clear();
	return true;
}

int BStyle::annexCount() const
{
	return member.annexes.size();
}
BStyle* BStyle::annex(int index)
{
	return member.annexes(index);
}
const BStyle* BStyle::annex(int index) const
{
	return member.annexes(index);
}

BStyle* BStyle::annex(const BString& name)
{
	for (int i = 0; i < member.annexes.size(); i++)
	{
		BStyle* annex = member.annexes[i];
		if (annex->name() == name)
			return annex;
	}
	return 0;
}
const BStyle* BStyle::annex(const BString& name) const
{
	for (int i = 0; i < member.annexes.size(); i++)
	{
		BStyle* annex = member.annexes[i];
		if (annex->name() == name)
			return annex;
	}
	return 0;
}

BStyle* BStyle::annex(const char* name)
{
	for (int i = 0; i < member.annexes.size(); i++)
	{
		BStyle* annex = member.annexes[i];
		if (annex->name() == name)
			return annex;
	}
	return 0;
}
const BStyle* BStyle::annex(const char* name) const
{
	for (int i = 0; i < member.annexes.size(); i++)
	{
		BStyle* annex = member.annexes[i];
		if (annex->name() == name)
			return annex;
	}
	return 0;
}

